// 特征类概念
// 特征类（Traits）是C++模板编程中的一种技术，用于在编译期获取和操作类型信息。特征类允许我们：
1.为类型定义统一的接口
2.为不同类型提供不同的行为
3.在编译期进行类型计算和转换

// --------------------------------------------------------------------
// 19.1 累加序列示例
// 这一节通过一个简单的例子介绍特征类的基本概念：如何实现一个通用的累加函数，可以处理不同类型的序列。

// 问题描述
// 我们需要实现一个函数，可以计算任意容器中所有元素的总和。挑战在于：
1.不同容器存储不同类型的元素
2.累加结果的类型可能与元素类型不同
3.需要一个合适的初始值

// 初步实现
template<typename Iterator>
auto accum(Iterator start, Iterator end)
{
    using ValueType = typename std::iterator_traits<Iterator>::value_type;
    ValueType total{}; // 使用值初始化获得默认值
    
    while (start != end) {
        total += *start;
        ++start;
    }
    return total;
}
// 这个实现存在几个问题：
1.返回类型被限制为容器元素的类型
2.对于某些类型（如字符），累加可能导致意外结果

// --------------------------------------------------------------
// 引入AccumTraits特征类
// 为了解决上述问题，引入特征类来定义累加操作的属性：

template<typename T>
struct AccumTraits;

// 针对char类型的特化
template<>
struct AccumTraits<char> {
    using AccT = int;         // 累加类型
    static AccT zero() {      // 初始值
        return 0;
    }
};

// 针对short类型的特化
template<>
struct AccumTraits<short> {
    using AccT = int;
    static AccT zero() {
        return 0;
    }
};

// 针对int类型的特化
template<>
struct AccumTraits<int> {
    using AccT = long;
    static AccT zero() {
        return 0;
    }
};

// 针对unsigned int类型的特化
template<>
struct AccumTraits<unsigned int> {
    using AccT = unsigned long;
    static AccT zero() {
        return 0;
    }
};

// 针对float类型的特化
template<>
struct AccumTraits<float> {
    using AccT = double;
    static AccT zero() {
        return 0.0;
    }
};

// 改进后的累加函数
template<typename Iterator>
auto accum(Iterator start, Iterator end)
{
    // 获取迭代器指向的元素类型
    // ::value_type 迭代器的特征
    using ValueType = typename std::iterator_traits<Iterator>::value_type;
    
    // 使用特征类确定累加类型和初始值
    using AccT = typename AccumTraits<ValueType>::AccT;
    AccT total = AccumTraits<ValueType>::zero();
    
    while (start != end) {
        total += *start;
        ++start;
    }
    return total;
}

// 使用示例
#include <iostream>
#include <vector>

int main()
{
    // 字符数组
    char chars[] = "hello";
    int sum = accum(chars, chars+5);  // 使用int累加，而不是char
    std::cout << "Sum of chars: " << sum << std::endl;
    
    // 整数向量
    std::vector<int> ints{1, 2, 3, 4, 5};
    long sumInts = accum(ints.begin(), ints.end());  // 使用long累加
    std::cout << "Sum of ints: " << sumInts << std::endl;
    
    // 浮点数组
    float floats[] = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f};
    double sumFloats = accum(floats, floats+5);  // 使用double累加
    std::cout << "Sum of floats: " << sumFloats << std::endl;
    
    return 0;
}

// -------------------------------------------------------
// 特征类的优势
1.类型安全：为每种类型选择适当的累加类型，避免溢出或精度丢失
2.灵活性：可以为任何类型定义特化版本
3.可扩展性：用户可以为自定义类型提供特化
4.编译期计算：类型选择在编译期完成，没有运行时开销

// 关键点总结
1.特征类提供了一种方式来关联类型与其属性
2.通过模板特化，可以为不同类型定制行为
3.特征类通常包含类型定义和静态函数
4.使用特征类可以编写更通用、更安全的代码
